#include <brpc/channel.h>         // brpc框架的Channel头文件，提供与服务器通信的功能
#include <thread>                  // C++标准库中的线程管理头文件，用于模拟异步调用的延迟
#include "main.pb.h"               // 由Protocol Buffers自动生成的头文件，定义了服务和消息的结构

// 异步RPC调用的回调函数，处理服务器响应
void callback(brpc::Controller* cntl, ::example::EchoResponse* response) {
    std::unique_ptr<brpc::Controller> cntl_guard(cntl);   // 使用unique_ptr管理cntl对象，确保内存自动释放
    std::unique_ptr<example::EchoResponse> resp_guard(response); // 同上，管理响应对象

    if (cntl->Failed() == true) {  // 检查RPC调用是否失败
        std::cout << "Rpc调用失败：" << cntl->ErrorText() << std::endl;
        return;  // 如果调用失败，直接返回
    }

    std::cout << "收到响应: " << response->message() << std::endl;  // 输出服务器返回的响应消息
}

int main(int argc, char *argv[])
{
    // 1. 创建并初始化RPC通信信道（Channel），用于与服务器进行连接
    brpc::ChannelOptions options;        // 定义Channel配置选项
    options.connect_timeout_ms = -1;     // 设置连接超时为-1，表示一直等待连接
    options.timeout_ms = -1;             // 设置请求超时为-1，表示一直等待响应
    options.max_retry = 3;               // 设置最大重试次数为3次
    options.protocol = "baidu_std";      // 设置通信协议为baidu_std，brpc默认的协议

    brpc::Channel channel;               // 创建一个brpc的Channel对象
    int ret = channel.Init("127.0.0.1:8080", &options);  // 初始化信道，连接到指定的服务器地址（localhost:8080）
    if (ret == -1) {                     // 如果信道初始化失败，输出错误信息并退出
        std::cout << "初始化信道失败！\n";
        return -1;
    }

    // 2. 创建服务存根（Stub）对象，用于调用远程的Echo服务
    example::EchoService_Stub stub(&channel);  // 创建一个EchoService_Stub对象，绑定到Channel

    // 3. 创建请求并发送异步RPC调用
    example::EchoRequest req;                   // 创建EchoRequest对象，用于设置请求消息
    req.set_message("你好~RPC~！");             // 设置请求消息内容

    brpc::Controller *cntl = new brpc::Controller();  // 创建Controller对象，管理RPC调用
    example::EchoResponse *rsp = new example::EchoResponse();  // 创建EchoResponse对象，用于接收响应
    
    ////////////////////////////////////
    // 同步调用方式
    ///////////////////////////////////
    stub.Echo(cntl, &req, rsp, nullptr);
    if (cntl->Failed() == true) {
        std::cout << "Rpc调用失败：" << cntl->ErrorText() << std::endl;
        return -1;
    }
    std::cout << "收到响应: " << rsp->message() << std::endl;
    delete cntl;
    delete rsp;

    /////////////////////////////////
    // 使用Google Protobuf提供的回调函数封装工具来创建异步回调
    ////////////////////////////////
    // auto clusure = google::protobuf::NewCallback(callback, cntl, rsp);  // 创建回调函数closure
    // stub.Echo(cntl, &req, rsp, clusure);  // 发送异步RPC请求，并指定完成后的回调函数

    // std::cout << "异步调用结束！\n";  // 主线程继续执行，输出异步调用结束的提示

    // 为了让异步调用有足够时间完成，主线程休眠3秒
    // std::this_thread::sleep_for(std::chrono::seconds(3));  // 主线程休眠3秒，确保回调能够被执行

    return 0;  
}
